package com.simp.run;

import com.simp.costant.Constant;
import com.simp.entity.SysLogEntity;
import com.simp.service.SysLogService;
import com.simp.utils.DbUtils;
import com.simp.utils.ExceptionUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 定时任务
 *
 * @author pan.shun
 * @version 2.0
 * @since 2022/3/24 22:23
 */
@Slf4j
@Component
public class ScheduleTask {

    @Autowired
    private DbUtils dbUtils;

    @Autowired
    private SysLogService sysLogService;

    private static final String filePath = new File("").getAbsolutePath() + File.separator + "file/";

    private final SimpleDateFormat FORMAT = new SimpleDateFormat("yyyyMMdd");

    /**
     * 清理近几天之外的文件
     */
    private final Integer EARLY_DAY = 5;

    /**
     * 每天凌晨一点执行
     */
    @Scheduled(cron = "0 0 1 * * ?")
    public void execute() {
        log.info("执行DDL备份 ，当前时间 :{}", FORMAT.format(new Date()));
        // ddl 备份
        startBakDb();

        // 清理历史数据
        clearEarlyDayFile();
    }

    /**
     * 数据库备份
     */
    private void startBakDb() {
        long startTime = System.currentTimeMillis();
        try {
            File file = new File(filePath);
            if (!file.exists()) {
                file.mkdir();
            }
            String fileName = FORMAT.format(new Date()) + "_bak.txt";
            FileWriter fileWriter = new FileWriter(filePath + fileName);
            List<String> tableNameList = dbUtils.getTableNameList();
            for (String t : tableNameList) {
                log.info("表名：{} DDL 开始备份 ", t);
                String ddl = dbUtils.getDDL(t);
                fileWriter.write("============" + t + "============" + "\r\n");
                fileWriter.write(ddl);
                fileWriter.write("\r\n");
            }
            fileWriter.close();
        } catch (IOException e) {
            log.error("数据库DDL备份异常 :{}", ExceptionUtils.print(e));
            SysLogEntity sysLogEntity = new SysLogEntity();
            sysLogEntity.setEventContent("DDL备份异常");
            sysLogEntity.setActionEvent(Constant.LOG_EVENT.ERROR);
            sysLogEntity.setStatus(Constant.LOG_STATUS.FAIL);
            sysLogEntity.setException(ExceptionUtils.print(e));
            sysLogService.saveAspectLog(sysLogEntity, startTime);
        }
    }

    /**
     * 清理近几天的之外数据
     */
    private void clearEarlyDayFile() {
        long startTime = System.currentTimeMillis();
        try {
            List<Integer> dayList = new ArrayList<>(16);
            String currentTime = FORMAT.format(new Date());
            Integer current = Integer.valueOf(currentTime);
            File file = new File(filePath);
            if (file.exists()) {
                File[] files = file.listFiles();
                if (files == null) {
                    return;
                }
                for (File f : files) {
                    String name = f.getName();
                    String time = name.substring(0, name.lastIndexOf("_"));
                    dayList.add(Integer.valueOf(time));
                }
            }
            int offset = current - EARLY_DAY;

            if (!CollectionUtils.isEmpty(dayList)) {
                dayList.forEach(r -> {
                    if (r <= offset) {
                        // 这里是需要删除的
                        File deleteFile = new File(filePath + r + "_bak.txt");
                        if (deleteFile.isFile() && deleteFile.exists()) {
                            deleteFile.delete();
                        }
                    }
                });
            }
        } catch (Exception e) {
            log.error("清理数据中发生了异常，异常信息 {}");
            SysLogEntity sysLogEntity = new SysLogEntity();
            sysLogEntity.setEventContent("DDL定期清理异常");
            sysLogEntity.setActionEvent(Constant.LOG_EVENT.ERROR);
            sysLogEntity.setStatus(Constant.LOG_STATUS.FAIL);
            sysLogEntity.setException(ExceptionUtils.print(e));
            sysLogService.saveAspectLog(sysLogEntity, startTime);
        }
    }
}
